package com.data.modules.smzh.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.data.common.api.vo.Result;
import com.data.common.constant.enums.ProductEnum;
import com.data.common.util.*;
import com.data.modules.mqt.MqttPushClient;
import com.data.modules.smzh.entity.*;
import com.data.modules.smzh.mapper.FacedeviceMapper;
import com.data.modules.smzh.service.*;
import com.data.modules.smzh.vo.SmDeviceVo;
import com.data.modules.system.entity.User;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Credentials;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Description: facedevice
 * @Author: data-boot
 * @Date:   2022-11-29
 * @Version: V1.0
 */
@Service
@Slf4j
public class FacedeviceServiceImpl extends ServiceImpl<FacedeviceMapper, Facedevice> implements IFacedeviceService {

    @Autowired
    private FacedeviceMapper facedeviceMapper;
    @Autowired
    private IDevicebuildService iDevicebuildService;

    @Autowired
    private IPersonfacesyncService personfacesyncService;
    @Autowired
    private IAppimageService appimageService;

    @Autowired
    private MqttPushClient mqttPushClient;

    @Autowired
    private IRegisterappuserService appuserService;

    @Autowired
    private IBuildingService buildingService;

    @Value("${sendMqtt.url:}")
    private String sendMqttUrl;

    @Value("${sendMqtt.username:}")
    private String mqttUserName;

    @Value("${sendMqtt.password:}")
    private String mqttPassword;

    @Value("${entranceGuard.aesPassword:}")
    private String aesPassword;


    @Override
    @Transactional
    public Boolean addBindDevice(SmDeviceVo smDeviceVo) {

        Boolean flag = false;

        //{"serialNo":"18618367512","serialName":"测试","uniqueNo":"","type":0,"model":"STD-TEST"}

        // type =2 组装序列号

		/* if (ctx.request.body.type === 2) {
			 ctx.request.body.serialNo = _appid.app_id + ctx.request.body.uniqueNo + ctx.request.body.serialNo;
		 }
                const device = await ctx.service.deviceManage.findDeviceBySerialNo(ctx.request.body.serialNo);
*/
        //通过序列号查询是否存在  存在 则失败

        //组装相关数据
	/*	  const sql = 'REPLACE into faceDevice (serial_no,app_id,address,threshold,push_url, model,device_type, update_time,create_time) VALUES (?)';
            const values = [];
            const params = [];
		 values.push(_serialNo);
		 values.push(appId);
		 values.push(_serialName);
		 values.push(82);
		 values.push('https://www.tll-tech.com/face-server/api/v1.0/putLog');

		  if (uniqueNo !== '') {
                const obj = {
                    serial_no: _serialNo,
                    building_no: appId + uniqueNo,
                    type: _type,
                };
                await conn.insert('deviceBuild', obj);
            }
*/

        String url = "https://www.sm-ioe.com/face-server/api/v1.0/putLog";
        Facedevice facedevice = new Facedevice();
        BeanUtil.copyProperties(smDeviceVo,facedevice);
        facedevice.setAddress(smDeviceVo.getSerialName());
        facedevice.setThreshold(82);
        facedevice.setPushUrl(url);
        facedevice.setDeviceType(smDeviceVo.getGroupType());
        facedevice.setCreateTime(new Date());

        int i = facedeviceMapper.insert(facedevice);
        if(i == 1){

            if(ObjectUtil.isNotEmpty(smDeviceVo.getUniqueNo())){
                Devicebuild devicebuild = new Devicebuild();
                devicebuild.setBuildingNo(smDeviceVo.getAppId()+smDeviceVo.getUniqueNo());
                devicebuild.setSerialNo(facedevice.getSerialNo());
                devicebuild.setType(smDeviceVo.getType());

                iDevicebuildService.save(devicebuild);
            }

            flag = true;
        }

        return flag;
    }

    /**
     * 编辑设备管理
     * @param smDeviceVo
     * @return
     */
    @Override
    @Transactional
    public void updateBindDeviceInfo(SmDeviceVo smDeviceVo) {

        // 设备编号不会变更，appId 不会变更，只会 更新设备基本信息

        /**
         * 通过设备号 查询是否已经被绑定 ,  存在  判断 序列号是否为空， 是 则删除。 否则做更新处理
         *   设备号 未绑定情况，序列号不为空，直接进行绑定
         */
        Facedevice facedevice = new Facedevice();
        BeanUtil.copyProperties(smDeviceVo,facedevice);

        this.update(new Facedevice().setAddress(smDeviceVo.getSerialName()).setModel(smDeviceVo.getModel()),
                new UpdateWrapper<Facedevice>().lambda().eq(Facedevice::getAppId,facedevice.getAppId())
        .eq(Facedevice::getSerialNo,facedevice.getSerialNo()));

        //facedevice.getSerialNo()

        int i = iDevicebuildService.lambdaQuery().eq(Devicebuild::getSerialNo,facedevice.getSerialNo()).list().size();

        if(i ==0){
            if(ObjectUtil.isNotEmpty(smDeviceVo.getUniqueNo())){

                Devicebuild devicebuild = new Devicebuild();
                devicebuild.setType(smDeviceVo.getType());
                devicebuild.setSerialNo(smDeviceVo.getSerialNo());
                devicebuild.setBuildingNo(smDeviceVo.getAppId()+smDeviceVo.getUniqueNo());
                iDevicebuildService.save(devicebuild);
            }
        }else{
            if(ObjectUtil.isNotEmpty(smDeviceVo.getUniqueNo())){

                this.iDevicebuildService.update(new Devicebuild().setBuildingNo(smDeviceVo.getAppId()+smDeviceVo.getUniqueNo()).setType(smDeviceVo.getType()),
                        new UpdateWrapper<Devicebuild>().lambda().eq(Devicebuild::getSerialNo,smDeviceVo.getSerialNo()));
            }else{

                iDevicebuildService.deleteBySerialNo(smDeviceVo.getSerialNo());
            }
        }

    }

    @Override
    public List<Map> getDeviceByUserId(Integer userId) {


        return facedeviceMapper.queryDeviceByUserId(userId);
    }

    @Override
    public String getDoorPassword(String userid) {


        return facedeviceMapper.queryDoorPassword(userid);
    }

    @Override
    public int modifyOpenDoorPassword(String userid, String newOpenDoorPassword, String serNo) {
        return facedeviceMapper.updateDoorPassword(userid,newOpenDoorPassword,serNo);
    }

    @Override
    public List<Map> getPersonFace(String userid) {

        return facedeviceMapper.queryPersonFace(userid);
    }

    @Override
    public int delAppFace(String id, String serialNo) {

        //保存 照片同步信息 personFaceSync
        int i = personfacesyncService.savePersonFaceSync(id,serialNo);

        appimageService.removeById(id);

        return i;
    }

    @Override
    @Transactional
    public int addAppFace(User user) {
        //新增 人脸照片信息
        Appimage appimage = new Appimage();
        appimage.setImagePath(user.getImagePath());
        appimage.setName(user.getName());
        appimage.setRegisterId(Integer.valueOf(user.getId()));
        appimageService.save(appimage);

        int id = appimage.getId();

        Personfacesync synFace = new Personfacesync();
        synFace.setCreateTime(new Date());
        synFace.setUpdateTime(new Date());
        synFace.setSerialNo(user.getSerialNos().get(0));
        synFace.setUserId("app_"+id);
        synFace.setUserName(user.getName());
        synFace.setUserImage(user.getImagePath());
        synFace.setCardNumber("");
        synFace.setSync(0);
        synFace.setCmd(1);//新增人脸
        synFace.setErrorValue("0");
        personfacesyncService.save(synFace);
        if(ObjectUtil.isNotEmpty(synFace.getId())){
            return 1;
        }
        return 0;

    }

    @Override
    public int addInviteVisitors(VisitorInfo user) {

        String appId = "";
        String roomNo = "";
        String unitNo = "";
        String buildNo = "";
        String createBy = "";

        Building building = buildingService.lambdaQuery().eq(Building::getUniqueNo,user.getUserId()).one();

        if(ObjectUtil.isNotEmpty(building)){
            appId = String.valueOf(building.getAppId());
            roomNo = building.getRoomNo();
            unitNo = building.getUnitNo();
            buildNo = building.getBuildNo();
        }else{
            building = buildingService.queryInfoByAppRegistId(user.getUserId());
            appId = String.valueOf(building.getAppId());
            roomNo = building.getRoomNo();
            unitNo = building.getUnitNo();
            buildNo = building.getBuildNo();
        }

        AtomicInteger j= new AtomicInteger();

        createBy= this.queryDevelAccountMobileByAppID(appId);
        String finalAppId = appId;
        String finalRoomNo = roomNo;
        String finalUnitNo = unitNo;
        String finalBuildNo = buildNo;
        String finalCreateBy = createBy;
        //获取围墙机序列号
        //todo

        user.getSerialNos().stream().forEach(x->{

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // 从字符串中按照指定格式解析日期时间信息
            Map map = new HashMap();
            try {
                Date startTime = sdf.parse(user.getStartTime());
                Date endTime = sdf.parse(user.getEndTime());

                map.put("serial_no",x);
                map.put("password",user.getInviteCode());
                map.put("register_id",user.getUserId());
                map.put("start_time",startTime);
                map.put("end_time",endTime);
                map.put("app_id", finalCreateBy);
                map.put("room_no", finalRoomNo);
                map.put("build_no", finalUnitNo);
                map.put("unit_no", finalBuildNo);

            } catch (ParseException e) {
                log.error(e.getMessage(),e);
            }

            List list = new ArrayList();
            Map msgMap = new HashMap();
            msgMap.put("invitePassowrd",user.getInviteCode());
            msgMap.put("startTime",user.getStartTime());
            msgMap.put("endTime",user.getEndTime());
            list.add(msgMap);

            KamliClientUtil.doPostpushMsgUr(x,"inviteCode",list);

            j.set(appimageService.addVisitors(map));

        });
        return j.get();
    }

    @Override
    public IPage<Facedevice> pageList(Page<Facedevice> page, Facedevice facedevice) {

        return facedeviceMapper.pageList(page,facedevice);
    }

    @Override
    public Facedevice queryDeviceInfo(String serialNo, Integer type) {
        return facedeviceMapper.getDeviceInfo(serialNo,type);
    }

    @Override
    public List<SmDeviceVo> seachManageBaseInfo(SmDeviceVo smDeviceVo) {

        int strLength = smDeviceVo.getSerialNo().length();
        int length = 0;

        //通过设备型号查询绑定门口机基本信息
        if(ObjectUtil.equals(ProductEnum.SMW_721M.getCode(),smDeviceVo.getModel())) {//管理机
            length = strLength - 2;
        }else if(ObjectUtil.equals(ProductEnum.SMW_721A10.getCode(),smDeviceVo.getModel())){//门口机

            Devicebuild  devicebuild = iDevicebuildService.lambdaQuery().eq(Devicebuild::getSerialNo,smDeviceVo.getSerialNo()).one();
            if(ObjectUtil.isNotEmpty(devicebuild)){

                return facedeviceMapper.queryManageInfoByBuidingNo(devicebuild.getBuildingNo());
            }

        }else{//智慧屏
            length= strLength-4;

        }
        String serialNo = StringUtils.substring(smDeviceVo.getSerialNo(),0,length);

        return facedeviceMapper.seachManageInfoBySerialNo(serialNo,length);
    }

    @Override
    public Result doBindDevice(SmDeviceVo smDeviceVo, HttpServletRequest req) {

        try {
            String pwd = "PvUdG1";
            //Facedevice facedevice
            String appId = JwtIOTAuthUtil.getTokenByRequest(req);
            String reaAppId = "";
            if(ObjectUtil.isEmpty(appId)){
                return Result.error(10001,"无效token");
            }else{
                reaAppId = facedeviceMapper.queryDevelAppId(appId);
                smDeviceVo.setAppId(Integer.valueOf(reaAppId));
            }
            //通过appId 查询develApp 表

            String serialNo =  smDeviceVo.getSerialNo();
            if (smDeviceVo.getType() == 2) {//管理机
                serialNo = reaAppId + smDeviceVo.getUniqueNo() + serialNo;
                smDeviceVo.setSerialNo(serialNo);
            }else{

            }

            Facedevice facedevice= this.lambdaQuery().eq(Facedevice::getSerialNo,smDeviceVo.getSerialNo()).one();

            if(ObjectUtil.isNotEmpty(facedevice)){

                if(ObjectUtil.isNotEmpty(facedevice.getAppId())){
                    return Result.error(10001,"device is exist");
                }else{
                    this.removeById(facedevice.getId());
                }
            }

           /* int i = this.lambdaQuery().eq(Facedevice::getSerialNo,smDeviceVo.getSerialNo()).list().size();

            if(i>0){
                return Result.error(10001,"device is exist");
            }*/

            Boolean flag = this.addBindDevice(smDeviceVo);
            if(flag){
                // 通知
                if(ObjectUtil.equals(2,smDeviceVo.getType())){
                    pwd = "540039";
                }

                if(!KamliClientUtil.doPost(smDeviceVo.getSerialNo(),pwd)){
                    return Result.error(10003,"通知kamilis 失败！");
                };

            }else{
                // facedeviceService.save(facedevice);
                return Result.error(10003,"database failed");
            }
        } catch (Exception e) {
            return Result.error(10001,e.getMessage());
        }
        return Result.ok(0,"操作成功");
    }

    @Override
    public Result searchAllDevice(SmDeviceVo smDeviceVo, HttpServletRequest req) {

        String appId = JwtIOTAuthUtil.getTokenByRequest(req);
        String reaAppId = "";
        if(ObjectUtil.isEmpty(appId)){
            return Result.error(10001,"无效token");
        }else{
            reaAppId = facedeviceMapper.queryDevelAppId(appId);
            smDeviceVo.setAppId(Integer.valueOf(reaAppId));
        }


        List<Map> list = facedeviceMapper.queryDeviceByGroupBy(smDeviceVo);
        return Result.ok(0,list);


    }

    @Override
    public String queryDevelAppIdByToken(String token) {

        return facedeviceMapper.queryDevelAppId(token);
    }

    @Override
    public String queryDevelAccountMobileByAppID(String appId) {
        return facedeviceMapper.queryAccountMobile(appId);
    }

    @Override
    public void synMsgBySn(String sn) {

        this.update(new Facedevice().setStatus(1), new UpdateWrapper<Facedevice>().lambda().eq(Facedevice::getSerialNo,sn));
        //发送消息 新增卡
        List<Personfacesync> addCardlist = personfacesyncService.lambdaQuery().eq(Personfacesync::getSerialNo,sn).eq(Personfacesync::getSync,0).eq(Personfacesync::getCmd,"3").list();
        queryPageList(addCardlist,sn,"sendcardnum");

        //发送消息 删除卡
        List<Personfacesync> deleteCardlist = personfacesyncService.lambdaQuery().eq(Personfacesync::getSerialNo,sn).eq(Personfacesync::getSync,0).in(Personfacesync::getCmd,4,5).list();
        queryPageList(deleteCardlist,sn,"delcardnum");

        //发送消息 删除卡
        List<Personfacesync> deleteCard= personfacesyncService.queryDeleteCard(sn,2);
        queryPageList(deleteCard,sn,"delcardnum");

    }

    /**
     * 通过定时任务来发送mqtt 消息
     */
    @Override
    public void sendMqttMsg() {

       List<Facedevice> list = this.lambdaQuery().eq(Facedevice::getModel,ProductEnum.SMW_721AC.getCode()).list();

        list.stream().forEach(x->{
            this.synMsgBySn(x.getSerialNo());
        });


    }

    //调用mqtt 查询设备状态
    @Override
    public void queryMqttStatus() {
        //查询门禁机信息
        List<Facedevice>list = this.lambdaQuery().eq(Facedevice::getModel,ProductEnum.SMW_721AC.getCode()).list();
        list.stream().forEach(x->{

            if(!getReqCode(x.getSerialNo())){
                    x.setStatus(0);
                    this.updateById(x);
            }else{
                x.setStatus(1);
                this.updateById(x);
            }
        });
    }



    private boolean getReqCode(String clientId){

        boolean falg = false;
        try {
            String authorization = Credentials.basic(mqttUserName, mqttPassword);

            String url = "http://39.96.147.199:18083/api/v5/clients/mg"+clientId;
            Map<String,String> headers = new HashMap();
            headers.put("Content-Type", "application/json");
            headers.put("Authorization",authorization);

            Map<String, String> querys = new HashMap<String, String>();

            HttpResponse response = HttpUtils.doGet(url, "", "GET", headers, querys);

            Integer code = response.getStatusLine().getStatusCode();
            if(ObjectUtil.equals(200,code)){
                falg = true;
            }

        } catch (Exception e) {
            log.error("查询客户端id状态异常:{}", e.getMessage(),e);
        }
        return  falg;
    }

    private void queryPageList(List<Personfacesync> addCardlist,String sn,String func){
        double pageSize = 40;
        for (int page = 1; (page - 1) * pageSize < addCardlist.size(); page++) {
            //分页数据
            List<Personfacesync> pageList = addCardlist.stream().skip((long) ((page - 1) * pageSize))
                    .limit((long) pageSize)
                    .collect(Collectors.toList());

            List<Integer> idList = pageList.stream().map(Personfacesync::getId).collect(Collectors.toList());

            String para = pageList.stream().map(Personfacesync::getCardNumber).collect(Collectors.joining("A"));
            sendMqttMsg(sn,func,para);

            this.personfacesyncService.lambdaUpdate().in(Personfacesync::getId,idList).set(Personfacesync::getSync,1).update();

        }
    }

    private void sendMqttMsg(String sn,String func,String para){

        Map<String,Object> map = new HashMap<>();
        map.put("DevSn",sn);
        map.put("func",func);
        map.put("para",para);
        String json = JSON.toJSONString(map);
        String topic = "/qr_gate/"+sn+"/cmd";

        Map<String,Object> reqMap = new HashMap<>();
        reqMap.put("apiId",topic);
        reqMap.put("sign",json);
        String req = JSON.toJSONString(reqMap);
        log.info("sendMqttmsg" + req);

        mqttPushClient.publish(topic,json);

    }

    /**
     * 组装加密信息 发送mqtt
     * @param user
     * @return
     */
    @Override
    public String sendQrCode(VisitorInfo user,String mobile,List<String> doorList) {

      /*  //通过userId 查询 手机号
        String mobile = appuserService.queryUserMobile(user.getUserId());

        List<String> doorList = new ArrayList<>();
        if(ObjectUtil.isEmpty(mobile)){
            mobile = user.getUserId();
            //获取门禁机序列号
            doorList = facedeviceMapper.queryDeviceInfo(mobile).stream().filter(x->x.getModel().equals("SMW-721AC")).map(SmDeviceVo::getSerialNo).collect(Collectors.toList());
        }*/
        String card = "C"+mobile+"D0";
        String limitNum = "N199";
        String result = aesEncry(user.getStartTime(),user.getEndTime(),card,limitNum);
        if(ObjectUtil.isNotNull(result)){
            //发送mqtt
            String finalMobile = mobile;
            user.getSerialNos().stream().forEach(x->{
                sendMqttMsg(x,"sendcardnum", finalMobile);
                sendMqttMsg(x,"sendcardnum",result);
            });

            doorList.stream().forEach(y->{
                sendMqttMsg(y,"sendcardnum", finalMobile);
                sendMqttMsg(y,"sendcardnum",result);
            });
        }

        return result;
    }

    @Override
    public String queryMobile(String userId) {

        //通过userId 查询 手机号
        String mobile = appuserService.queryUserMobile(userId);

        List<String> doorList = new ArrayList<>();
        if(ObjectUtil.isEmpty(mobile)){
            mobile = userId;
        }
        return mobile;
    }

    @Override
    public List<SmDeviceVo> queryDeviceList(String mobile) {
        return  facedeviceMapper.queryDeviceInfo(mobile);
    }

    @Override
    public List<String> queryAppRegistId(String uniqueNo) {

        return facedeviceMapper.queryAppRegistId(uniqueNo);
    }

    private String aesEncry(String startTime,String endTime,String card,String limitNum){

        String result = "";
        try {

            Date date = DateUtils.parseDate(startTime, "yyyy-MM-dd HH:mm:ss");
            String start = DateUtil.format(date, "yyyyMMddHHmmss");

            Date edate = DateUtils.parseDate(endTime, "yyyy-MM-dd HH:mm:ss");
            String end = DateUtil.format(edate, "yyyyMMddHHmmss");

            long nowDate = DateUtils.getCurrentTimestamp();
           // String str = "Q"+end+"T"+start+"X"+nowDate+"S120"+card+limitNum;
            String str = "Q"+end+"T"+start+"X"+end+"S120"+card+limitNum;

            result = AESZeroUtils.encrypt(str,aesPassword); // 加密

            log.info("二维码请求参数{}",str);
            log.info("二维码请求加密结果{}",result);
        } catch (Exception e) {
            log.error("二维码请求",e.getMessage(),e);
        }
         return result.replaceAll("\\r\\n","");
    }
}
